package ca.krakenpower.kvoxels;

public class Camera {
	
	private Quaternion orientation;
	private Vector3 position;
	
	private double depthOfField;
	private double fieldOfView;
	private int imageWidth, imageHeight;
	private double sampleRate;
	private double nearPlaneDist;
	
	public Camera(double dof, double fov, double npd) {
		this.orientation = Quaternion.get(0, Vector3.FWD);
		this.position = Vector3.ZERO;
		this.depthOfField = dof;
		this.fieldOfView = fov;
		this.nearPlaneDist = npd;
	}
	
	public double getNearPlaneDistance() {
		return nearPlaneDist;
	}
	
	public double getNearPlaneSize() {
		return 2 * nearPlaneDist * Math.tan(fieldOfView / 2);
	}
	
	public int getImageWidth() {
		return imageWidth;
	}
	
	public void setImageSize(int width, int height) {
		imageWidth = width;
		imageHeight = height;
	}
	
	public int getImageHeight() {
		return imageHeight;
	}
	
	public double getSampleRate() {
		return sampleRate;
	}
	
	public void setSampleRate(double rate) {
		sampleRate = rate;
	}
	
	public double depthOfField() {
		return depthOfField;
	}
	
	public double fieldOfView() {
		return fieldOfView;
	}
	
	public Vector3 getPosition() {
		return position;
	}
	
	public Quaternion getOrientation() {
		return orientation;
	}
	
	public void setPosition(Vector3 p) {
		if (p == null) {
			throw new IllegalArgumentException("null vector supplied for camera position");
		}
		
		this.position = p;
	}
	
	public void setOrientation(Quaternion o) {
		if (o == null) {
			throw new IllegalArgumentException("null quaternion supplied for camera orientation");
		}
		
		this.orientation = o;
	}
	
	public void move(double distance, Vector3 direction) {
		position = position.sum(direction.scale(distance));
	}
	
	public void rotate(double angle, Vector3 axis) {
		orientation = Quaternion.get(angle, axis).product(orientation);
	}
	
	public Vector3 localForward() {
		return orientation.rotate(Vector3.FWD);
	}
	
	public Vector3 localBackward() {
		return orientation.rotate(Vector3.BACK);
	}
	
	public Vector3 localRight() {
		return orientation.rotate(Vector3.RIGHT);
	}
	
	public Vector3 localLeft() {
		return orientation.rotate(Vector3.LEFT);
	}
	
	public Vector3 localUp() {
		return orientation.rotate(Vector3.UP);
	}
	
	public Vector3 localDown() {
		return orientation.rotate(Vector3.DOWN);
	}

}
